package model;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import utils.ScoredEntities;
import edu.stanford.nlp.ling.HasWord;
import edu.stanford.nlp.ling.TaggedWord;
import edu.stanford.nlp.tagger.maxent.MaxentTagger;

/**
 * The Document class employs the Stanford POS tagger to do some shallow
 * processing
 * 
 * @author Amos
 * 
 */
public class Document {
	private ArrayList<Sentence> sentences = new ArrayList<Sentence>();
	private String id;
	public final int T = 4;
	public char sep = Collection.getSeparator();

	public Document(MaxentTagger tagger, File file) {
		this.id = file.getName();
		try {
			removeNoise(file);
			List<List<HasWord>> sourceSentences = MaxentTagger
					.tokenizeText(new BufferedReader(new FileReader(file)));
			for (List<HasWord> sourceSentence : sourceSentences) {
				ArrayList<TaggedWord> taggedSentence = tagger
						.tagSentence(sourceSentence);
				sentences.add(new Sentence(taggedSentence));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void removeNoise(File file) {
		FileInputStream inputStream;
		try {
			inputStream = new FileInputStream(file);
			BufferedReader in = new BufferedReader(new InputStreamReader(
					inputStream));
			String string = in.readLine(), text = "";
			while (string != null) {
				if (System.getProperty("os.name").contains("Windows")) {
					text = text.concat(string + "\r\n");
				} else {
					text = text.concat(string + "\n");
				}
				string = in.readLine();
			}
			inputStream.close();

			while (text.contains("~")) {
				text = text.replace("~", "");
			}

			FileOutputStream outputStream = new FileOutputStream(file);
			outputStream.write(text.getBytes());
			outputStream.close();
		} catch (FileNotFoundException e) {
			System.out.println("Trying to read from " + file.toString());
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Save the document as a tagged document
	 */
	public void saveTagged(String targetFile) throws FileNotFoundException {

		PrintWriter writer;
		writer = new PrintWriter(targetFile);
		for (Sentence sentence : sentences) {
			writer.write(sentence.toString(true));
		}
		writer.close();
	}

	/**
	 * Save the file one sentence per line
	 * @param targetFile
	 * @throws FileNotFoundException
	 */
	public void saveLineByLine(String targetFile) throws FileNotFoundException {

		PrintWriter writer;
		writer = new PrintWriter(targetFile);
		for (Sentence sentence : sentences) {
			writer.write(sentence.toString(false) + "\n");
		}
		writer.close();
	}	
	
	/**
	 * Save the slices to file, window size specified by user. Note that the
	 * punctuation marks are also included as tokens.
	 * 
	 * @param windowSize
	 *            The size (by tokens) of the window specified by the user
	 * @param justValue
	 *            if true, will save only the word itself, but not the tag
	 * @param location
	 *            the location where the slices should be saved to
	 * @throws FileNotFoundException
	 */
	public void saveWindows(int windowSize, String location)
			throws FileNotFoundException {

		// System.out.println("sentences size: "+sentences.size());
		StringBuffer window = new StringBuffer();
		for (int i = 0; i < sentences.size(); i++) {
			int sliceLength = 0;
			for(int j = i; j < sentences.size(); j++) {
				if(sliceLength + sentences.get(j).size() <= windowSize) {
					sliceLength += sentences.get(j).size();
					window.append(listToString(sentences.get(j)));
				}
			}

			// windows.add(window.toString());
			PrintWriter writer;
			writer = new PrintWriter(location + sep + id + "." + i + ".txt");
			writer.write(window.toString());
			writer.close();
			System.out.println(id + " window " + i);
			// System.out.println(" ");
		}
	}

	private String listToString(ArrayList<TaggedWord> arrayList) {
		String toReturn = "";
		for (TaggedWord word : arrayList) {
			toReturn = toReturn.concat(word.toString() + " ");
		}
		return toReturn;
	}

	/**
	 * Calculate the score of a sentence given the word-score mapping
	 * 
	 * @param v
	 *            The vocabulary that provides the word - score mapping
	 * 
	 * @param location
	 *            The location of the file to save to
	 * 
	 * 
	 * @return the score of the sentence
	 */
	public void scoreByLexicon(ScoredEntities v, String location,
			boolean longTermFirst, boolean normalize) {
		double scores[] = new double[sentences.size()];

		int index = 0;
		for (Sentence sentence : sentences) {
			scores[index] = sentence.scoreSum(v, longTermFirst);
			index++;
		}

		if (normalize) {
			double min = scores[0];
			double max = scores[0];

			for (int i = 0; i < scores.length; i++) {
				if (scores[i] < min) {
					min = scores[i];
				}

				if (max < scores[i]) {
					max = scores[i];
				}
			}

			for (int i = 0; i < scores.length; i++) {
				double value = scores[i];
				value = (value - min) / (max - min);
				scores[i] = value;
			}
		}
		PrintWriter writer;
		try {
			writer = new PrintWriter(location + sep + id + ".score");

			for (int i = 0; i < scores.length; i++) {
				writer.write(i + " " + scores[i]);
				writer.write("\n");
			}
			// System.out.println("Writing to " + location + sep + id + ".lgl");
			writer.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void scoreAssoc(ScoredEntities v, String location,
			boolean longTermFirst) {
		double scores[] = new double[sentences.size()];
		PrintWriter writer;
		try {
			writer = new PrintWriter(location + sep + id + ".lgl");
			int count = 2;
			int end = 3;

			for (int i = 0; i < scores.length; i++) {
				int start = i + 2;
				for (end = start + 1; end < scores.length + 2; end++) {
					writer.write(start
							+ " "
							+ end
							+ " "
							+ (end - start <= 4 ? Math.pow(Math.E,
									1 - (end - start)) : 0) + "\n");
				}

				writer.write("0 " + count + " " + (1 - scores[i]));
				writer.write("\n");
				writer.write(count + " 1 " + scores[i]);
				writer.write("\n");
				count++;
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Test
	 * 
	 * @param args
	 */
	public static void main(String args[]) {
		MaxentTagger tagger;
		try {
			tagger = new MaxentTagger(
					"./models/bidirectional-distsim-wsj-0-18.tagger");
			Document d = new Document(
					tagger,
					new File(
							"/home/s3157645/workspace/Data/Summary/DegreeSummary/BLOG06-20060219-022-0023571889__0.orig.txt.graph_degreeSummary.txt"));
			d.saveTagged("/home/s3157645/workspace/Data/Summary/DegreeSummary/test");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
